/**
 * @file    drv_uart.c
 * @brief   MCU驱动-串口驱动
 * @author  Liuwei
 * @version 1.0.1
 * @date    2023-04-18
 * 
 * @copyright Copyright (c) 2023 JBD-Energy Storage Technology Co. LTD
 * 
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version   <th>Author   <th>Description
 * <tr><td>2023-04-18 <td>1.0.1     <td>Liuwei   <td>首次创建
 * </table>
 */
/* includes ------------------------------------------------------------------*/
#include "drv_uart.h"
#include "drv_gpio.h"
#include "drv_mcu.h"
/* macro/define --------------------------------------------------------------*/
#define UART_TIMEOUT   (20)
/* typedef -------------------------------------------------------------------*/
/**
 * @brief 定义串口对象
 */
typedef struct 
{
	UART_T* uart;
	uart_rx_cb_func pfunc;
}uart_obj_type;
/* local functions -----------------------------------------------------------*/

/* static variables ----------------------------------------------------------*/
static uart_obj_type uart_obj[DRV_UART_MAX] = 
{
	{UART0 , NULL },
	{UART1 , NULL },
	{UART2 , NULL },
	{UART3 , NULL },
	{UART4 , NULL },
	{UART5 , NULL },
	{UART6 , NULL },
	{UART7 , NULL },
};

/* global variables ----------------------------------------------------------*/

/** ------------------------------------------------------------------------- *
  *                             Global function
 ** ------------------------------------------------------------------------- */
void drv_uart_init(uint8_t uart_id , uint32_t baudrate)
{
	SYS_UnlockReg();
	
	switch(uart_id)
	{
		case DRV_UART0:
			CLK_EnableModuleClock(UART0_MODULE);
			if(0 == (CLK->CLKDSTS & CLK_CLKDCTL_HXTFQIEN_Msk))
				CLK->CLKSEL1 = (CLK->CLKSEL1 & ~CLK_CLKSEL1_UART0SEL_Msk) | (0x0 << CLK_CLKSEL1_UART0SEL_Pos);
			/* Set PA0-RXD PA1-TXD */
    		SYS->GPA_MFPL &= ~(SYS_GPA_MFPL_PA0MFP_Msk | SYS_GPA_MFPL_PA1MFP_Msk);
    		SYS->GPA_MFPL |= (SYS_GPA_MFPL_PA0MFP_UART0_RXD | SYS_GPA_MFPL_PA1MFP_UART0_TXD);
			NVIC_EnableIRQ(UART0_IRQn);
			UART_EnableInt(UART0, (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk));
			
			UART_Open(UART0, baudrate);
			break;
		case DRV_UART1:
			CLK_EnableModuleClock(UART1_MODULE);
			if(0 == (CLK->CLKDSTS & CLK_CLKDCTL_HXTFQIEN_Msk))
				CLK->CLKSEL1 = (CLK->CLKSEL1 & ~CLK_CLKSEL1_UART1SEL_Msk) | (0x0 << CLK_CLKSEL1_UART1SEL_Pos);

			/* Set PD10-RXD PD11-TXD */
    		SYS->GPD_MFPH &= ~(SYS_GPD_MFPH_PD10MFP_Msk | SYS_GPD_MFPH_PD11MFP_Msk);
    		SYS->GPD_MFPH |= (SYS_GPD_MFPH_PD10MFP_UART1_RXD | SYS_GPD_MFPH_PD11MFP_UART1_TXD);
			NVIC_EnableIRQ(UART1_IRQn);
			UART_EnableInt(UART1, (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk));
			UART_Open(UART1, baudrate); 
			break;
		case DRV_UART2:
			CLK_EnableModuleClock(UART2_MODULE);
			if(0 == (CLK->CLKDSTS & CLK_CLKDCTL_HXTFQIEN_Msk))
				CLK->CLKSEL1 = (CLK->CLKSEL1 & ~CLK_CLKSEL3_UART2SEL_Msk) | (0x0 << CLK_CLKSEL3_UART2SEL_Pos);

    		SYS->GPE_MFPH &= ~(SYS_GPE_MFPH_PE8MFP_Msk | SYS_GPE_MFPH_PE9MFP_Msk);
    		SYS->GPE_MFPH |= (SYS_GPE_MFPH_PE8MFP_UART2_TXD | SYS_GPE_MFPH_PE9MFP_UART2_RXD);
			NVIC_EnableIRQ(UART2_IRQn);
			UART_EnableInt(UART2, (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk));
			UART_Open(UART2, baudrate);
            /* RS485 I/O */
			break;
        case DRV_UART3:
			CLK_EnableModuleClock(UART3_MODULE);
			if(0 == (CLK->CLKDSTS & CLK_CLKDCTL_HXTFQIEN_Msk))
				CLK->CLKSEL1 = (CLK->CLKSEL1 & ~CLK_CLKSEL3_UART3SEL_Msk) | (0x0 << CLK_CLKSEL3_UART3SEL_Pos);

    		SYS->GPE_MFPH &= ~(SYS_GPE_MFPH_PE10MFP_Msk | SYS_GPE_MFPH_PE11MFP_Msk);
    		SYS->GPE_MFPH |= (SYS_GPE_MFPH_PE10MFP_UART3_TXD | SYS_GPE_MFPH_PE11MFP_UART3_RXD);
			NVIC_EnableIRQ(UART3_IRQn);
			UART_EnableInt(UART3, (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk));
			UART_Open(UART3, baudrate);
			break;
		case DRV_UART5:
			CLK_EnableModuleClock(UART5_MODULE);
			if(0 == (CLK->CLKDSTS & CLK_CLKDCTL_HXTFQIEN_Msk))
				CLK->CLKSEL1 = (CLK->CLKSEL1 & ~CLK_CLKSEL3_UART5SEL_Msk) | (0x0 << CLK_CLKSEL3_UART5SEL_Pos);

			/* Set PA4-RXD PA5-TXD */
    		SYS->GPA_MFPL &= ~(SYS_GPA_MFPL_PA4MFP_Msk | SYS_GPA_MFPL_PA5MFP_Msk);
    		SYS->GPA_MFPL |= (SYS_GPA_MFPL_PA4MFP_UART5_RXD | SYS_GPA_MFPL_PA5MFP_UART5_TXD);
			NVIC_EnableIRQ(UART5_IRQn);
			UART_EnableInt(UART5, (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk));
			UART_Open(UART5, baudrate);
			break;
		case DRV_UART6:
			CLK_EnableModuleClock(UART6_MODULE);
			if(0 == (CLK->CLKDSTS & CLK_CLKDCTL_HXTFQIEN_Msk))
				CLK->CLKSEL1 = (CLK->CLKSEL1 & ~CLK_CLKSEL3_UART6SEL_Msk) | (0x0 << CLK_CLKSEL3_UART6SEL_Pos);

			/* Set PC11-RXD PC12-TXD */
    		SYS->GPC_MFPH &= ~(SYS_GPC_MFPH_PC11MFP_Msk | SYS_GPC_MFPH_PC12MFP_Msk);
    		SYS->GPC_MFPH |= (SYS_GPC_MFPH_PC11MFP_UART6_RXD | SYS_GPC_MFPH_PC12MFP_UART6_TXD);
			NVIC_EnableIRQ(UART6_IRQn);
			UART_EnableInt(UART6, (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk));
			UART_Open(UART6, baudrate);
            /* RS485 I/O */
            drv_gpio_cfg_mode(RS485_DE2_PORT , RS485_DE2_PIN ,GPIO_MODE_OUTPUT);
            drv_gpio_reset_pin(RS485_DE2_PORT , RS485_DE2_PIN);
			break;
		case DRV_UART7:
			CLK_EnableModuleClock(UART7_MODULE);
			if(0 == (CLK->CLKDSTS & CLK_CLKDCTL_HXTFQIEN_Msk))
				CLK->CLKSEL3 = (CLK->CLKSEL3 & ~CLK_CLKSEL3_UART7SEL_Msk) | (0x0 << CLK_CLKSEL3_UART7SEL_Pos);

			/* Set PA8-RXD PA9-TXD */
    		SYS->GPA_MFPH &= ~(SYS_GPA_MFPH_PA8MFP_Msk | SYS_GPA_MFPH_PA9MFP_Msk);
    		SYS->GPA_MFPH |= (SYS_GPA_MFPH_PA8MFP_UART7_RXD | SYS_GPA_MFPH_PA9MFP_UART7_TXD);
			NVIC_EnableIRQ(UART7_IRQn);
			UART_EnableInt(UART7, (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk));
			UART_Open(UART7, baudrate); 
            /* RS485 I/O */
            drv_gpio_cfg_mode(RS485_DE1_PORT , RS485_DE1_PIN ,GPIO_MODE_OUTPUT);
            drv_gpio_reset_pin(RS485_DE1_PORT , RS485_DE1_PIN);
			break;
		default:
			break;
	}
	
	SYS_LockReg();
}

void drv_uart_deinit(uint8_t uart_id)
{
	switch(uart_id)
	{
		case DRV_UART0:
			NVIC_DisableIRQ(UART0_IRQn);
			UART_DisableInt(UART0, (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk));
			UART_Close(UART0);
			break;
		case DRV_UART1:
			NVIC_DisableIRQ(UART1_IRQn);
			UART_DisableInt(UART1, (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk));
			UART_Close(UART1);
			break;
		case DRV_UART2:
			NVIC_DisableIRQ(UART2_IRQn);
			UART_DisableInt(UART2, (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk));
			UART_Close(UART2);
			break;
		case DRV_UART3:
			NVIC_DisableIRQ(UART3_IRQn);
			UART_DisableInt(UART3, (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk));
			UART_Close(UART3);
			break;
		case DRV_UART4:
			NVIC_DisableIRQ(UART4_IRQn);
			UART_DisableInt(UART4, (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk));
			UART_Close(UART4);
			break;
		case DRV_UART5:
			NVIC_DisableIRQ(UART5_IRQn);
			UART_DisableInt(UART5, (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk));
			UART_Close(UART5);
			break;
		case DRV_UART6:
			NVIC_DisableIRQ(UART6_IRQn);
			UART_DisableInt(UART6, (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk));
			UART_Close(UART6);
			break;
		case DRV_UART7:
			NVIC_DisableIRQ(UART7_IRQn);
			UART_DisableInt(UART7, (UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk));
			UART_Close(UART7);
			break;
		default:
			break;
	}
}

/**
 * @brief  串口接收回调函数
 * @param  uart_id : 串口ID 
 * @param  pfunc : 接受回调函数
 * @return  void
 */
void drv_uart_set_rx_cb(uint8_t uart_id , uart_rx_cb_func pfunc)
{
	if(uart_id >= DRV_UART_MAX)
		return ;

	uart_obj[uart_id].pfunc = pfunc;
}

/**
 * @brief  串口发送字符串
 * @param  uart_id : 串口ID 
 * @param  sbuf : 发送缓冲去
 * @param  send_num : 发送数量
 */
void drv_uart_send_str(uint8_t uart_id ,uint8_t *sbuf ,uint32_t send_num)
{
    uint16_t timeout = 0;
	if(uart_id >= DRV_UART_MAX)
		return ;
    
    switch(uart_id)
    { 
        case DRV_UART0:
			break;
		case DRV_UART1:
			break;
		case DRV_UART2:
			break;
		case DRV_UART3:
			break;
		case DRV_UART4:
			break;
		case DRV_UART5:
			break;
		case DRV_UART6:
            drv_gpio_set_pin(RS485_DE2_PORT , RS485_DE2_PIN);
            uart_delay_ms(2);
			break;
		case DRV_UART7:
            drv_gpio_set_pin(RS485_DE1_PORT , RS485_DE1_PIN);
            uart_delay_ms(2);
			break;
		default:
			break;
    }
    
    UART_Write(uart_obj[uart_id].uart , sbuf , send_num);
    
    timeout = 0;
    while(UART_IS_TX_EMPTY(uart_obj[uart_id].uart) == 0)
    {
        ++ timeout;
		uart_delay_ms(1);
        if(timeout >= UART_TIMEOUT)
            break;
    }
   
    switch(uart_id)
    { 
        case DRV_UART0:
			break;
		case DRV_UART1:
			break;
		case DRV_UART2:
			break;
		case DRV_UART3:
			break;
		case DRV_UART4:
			break;
		case DRV_UART5:
			break;
		case DRV_UART6:
            uart_delay_ms(2);
            drv_gpio_reset_pin(RS485_DE2_PORT  , RS485_DE2_PIN);
			break;
		case DRV_UART7:
            uart_delay_ms(2);
            drv_gpio_reset_pin(RS485_DE1_PORT , RS485_DE1_PIN);
			break;
		default:
			break;
    }
}

void drv_uart_send_char(uint8_t uart_id ,uint8_t byte)
{
	uint32_t timeout = 0;
    if(uart_id >= DRV_UART_MAX)
		return ;
    
    timeout = 0;
    while(uart_obj[uart_id].uart->FIFOSTS & UART_FIFOSTS_TXFULL_Msk)
    {
        ++ timeout;
        if(timeout >= UART_TIMEOUT)
            break;
    }
    
    uart_obj[uart_id].uart->DAT = byte;
    
    timeout = 0;
    while(UART_IS_TX_EMPTY(uart_obj[uart_id].uart) == 0)
    {
        ++ timeout;
        if(timeout >= UART_TIMEOUT)
            break;
    }
    
    UART_Write(uart_obj[uart_id].uart , &byte , 1);
}
/** ------------------------------------------------------------------------- *
  *                              Local function
 ** ------------------------------------------------------------------------- */
/**
 * @brief UART0接收函数
 */
void drv_uart0_recv_irq(uint8_t rx_data)
{
	if(uart_obj[DRV_UART0].pfunc != NULL)
		uart_obj[DRV_UART0].pfunc(DRV_UART0, rx_data);
} 

/**
 * @brief UART1接收函数
 */
void drv_uart1_recv_irq(uint8_t rx_data)
{
	if(uart_obj[DRV_UART1].pfunc != NULL)
		uart_obj[DRV_UART1].pfunc(DRV_UART1, rx_data);
} 

/**
 * @brief UART2接收函数
 */
void drv_uart2_recv_irq(uint8_t rx_data)
{
	if(uart_obj[DRV_UART2].pfunc != NULL)
		uart_obj[DRV_UART2].pfunc(DRV_UART2, rx_data);
} 

/**
 * @brief UART3接收函数
 */
void drv_uart3_recv_irq(uint8_t rx_data)
{
	if(uart_obj[DRV_UART3].pfunc != NULL)
		uart_obj[DRV_UART3].pfunc(DRV_UART3, rx_data);
} 

/**
 * @brief UART4接收函数
 */
void drv_uart4_recv_irq(uint8_t rx_data)
{
	if(uart_obj[DRV_UART4].pfunc != NULL)
		uart_obj[DRV_UART4].pfunc(DRV_UART4, rx_data);
} 

/**
 * @brief UART5接收函数
 */
void drv_uart5_recv_irq(uint8_t rx_data)
{
	if(uart_obj[DRV_UART5].pfunc != NULL)
		uart_obj[DRV_UART5].pfunc(DRV_UART5, rx_data);
} 

/**
 * @brief UART6接收函数
 */
void drv_uart6_recv_irq(uint8_t rx_data)
{
	if(uart_obj[DRV_UART6].pfunc != NULL)
		uart_obj[DRV_UART6].pfunc(DRV_UART6 , rx_data);
} 

/**
 * @brief UART7接收函数
 */
void drv_uart7_recv_irq(uint8_t rx_data)
{
	if(uart_obj[DRV_UART7].pfunc != NULL)
		uart_obj[DRV_UART7].pfunc(DRV_UART7 , rx_data);
} 

/********** Copyright (c) 2023 JBD-Energy Storage Technology Co. LTD *********/
